*** Figures 1, 2, 3. (2024-12-17)
***
*** DEFINITIONS: year=referendum, yearroll=roll call vote, Next=next leg election

use DATA_REP_20241217.dta, clear

drop if missing(prop)
drop if Last=="vacant"

egen propno = group(prop)
destring propno, replace
gen propch = propno
replace propch = propno + (0.1)*(Chamber=="Senate")
egen propchno = group(propch)

* Issure orientation (1=roll call, 2=ref vote, 3=sponsor)
gen issuevalid1 = (issuescore1==1) | (issuescore1==-1)
gen issuevalid2 = (issuescore2==1) | (issuescore2==-1)
gen issuevalid3 = (issuescore3==1) | (issuescore3==-1)

* Salience
gen sal = 1 if salience=="Low"
replace sal = 2 if salience=="Medium"
replace  sal = 3 if salience=="High"

* Repealed laws
gen repeal = 0
replace repeal=1 if (prop=="AK_2000_M6" | prop=="CA_2000_P30" | prop=="CA_2000_P31" | ///
  prop=="CA_2004_P72" | prop=="CA_2014_P48" | prop=="CA_2020_P25" | ///
  prop=="ME_2008_Q1" | prop=="MI_2006_0603" | ///
  prop=="ND_2016_RM1" | prop=="OH_2011_I2" | prop=="SD_2016_RL19" | prop=="SD_2016_RL20" | ///
  prop=="WA_2002_R53" | prop=="WA_2004_R55" | prop=="WA_2019_R88")
  
* General election
gen general=1
replace general=0 if (prop=="CA_2000_P29" | prop=="CA_2000_P30" | prop=="CA_2000_P31" | ///
  prop=="CA_2008_P94" | prop=="CA_2008_P95" | prop=="CA_2008_P96" | prop=="CA_2008_P97" | ///
  prop=="CO_2020_P113" | prop=="ND_2012_RM4" | prop=="ND_2016_RM1")
    
* District referendum returns
gen yespct = Yes/(Yes+No)
gen yes50 = max(yespct,1-yespct)
gen Votes=Demvote+Repvote
gen districtyes = (Yes>No) if ~missing(Yes) & ~missing(No)

* Roll call votes
gen rollvalid = (Vote=="Yes" | Vote=="No")
gen rollyes = 1 if Vote=="Yes" & rollvalid==1
replace rollyes = 0 if Vote=="No" & rollvalid==1
gen rollno = 1-rollyes if ~missing(Vote)

* Congruence
gen cong = (Vote=="Yes" & yespct>.5) | (Vote=="No" & yespct<.5) if rollvalid~=0

* Legislative district competitiveness
gen closeness = abs((Demvote-Repvote)/(Demvote+Repvote))
gen unopposed = (closeness==1)

* Green CA 2000 P30, P31 (Bock). Ind CA 2000 P29 (Kopp)
* Party control (AK=Rep, CA=Dem, CO=Dem, ME=Dem, MD=Dem, MI=Rep, ND=Rep, SD=Rep, WA=Dem except Senate 2003-2004 )
gen partycontrol = "Dem"
replace partycontrol = "Rep" if (state=="AK") | (state=="MI") | (state=="ND") | ///
 (state=="OH") | (state=="SD") | (state=="WA" & Chamber=="Senate" & year==2004)
gen party = 1 if Party=="Rep"
replace party = -1 if Party=="Dem" | Party=="Green" | (Party=="Ind" & state=="ME")
replace party = . if Party=="Ind" & state=="CA"
* CA independent Quentin Kopp did not caucus with either party. Originally Dem.
gen gop = 1 if party==1
replace gop = 0 if party==-1
gen majgop = (partycontrol=="Rep")
gen rollyesR = (rollyes==1)&(gop==1)
gen rollyesD = (rollyes==1)&(gop==0)
gen rollnoR = (rollno==1)&(gop==1)
gen rollnoD = (rollno==1)&(gop==0)

* Other variables
gen senate = (Chamber=="Senate")

* Ideology (ideotype=1 conservative, ideotype=-1 liberal)
gen ideo = np_score
gen ideoabs = abs(ideo)
gen ideotype=-1 if ~missing(ideo)
replace ideotype=1 if ideo>0 & ~missing(ideo)
gen ideoyes1 = 0 if ~missing(ideo) & issuevalid1==1
replace ideoyes1 = 1 if ((ideo>0 & issuescore1==1) | (ideo<0 & issuescore1==-1)) & ~missing(ideo) & issuevalid1==1
gen ideoyes2 = 0 if ~missing(ideo) & issuevalid2==1
replace ideoyes2 = 1 if ((ideo>0 & issuescore2==1) | (ideo<0 & issuescore2==-1)) & ~missing(ideo) & issuevalid2==1
gen ideoyes3 = 0 if ~missing(ideo) & issuevalid3==1
replace ideoyes3 = 1 if ((ideo>0 & issuescore3==1) | (ideo<0 & issuescore3==-1)) & ~missing(ideo) & issuevalid3==1

gen iyes1 = ideo*issuescore1 if issuevalid1==1
gen iyes2 = ideo*issuescore2 if issuevalid2==1
gen iyes3 = ideo*issuescore3 if issuevalid3==1

 
* District orientation on issue (-1 is liberal, +1 is conservative)
gen districtview1 = -1 if ((yespct<.5 & issuescore1==1) | (yespct>.5 & issuescore1==-1)) & issuevalid1==1
replace districtview1 = 1 if ((yespct>.5 & issuescore1==1)|(yespct<.5 & issuescore1==-1)) & issuevalid1==1
gen districtview2 = -1 if ((yespct<.5 & issuescore2==1) | (yespct>.5 & issuescore2==-1)) & issuevalid2==1
replace districtview2 = 1 if ((yespct>.5 & issuescore2==1)|(yespct<.5 & issuescore2==-1)) & issuevalid2==1
gen districtview3 = -1 if ((yespct<.5 & issuescore3==1) | (yespct>.5 & issuescore3==-1)) & issuevalid3==1
replace districtview3 = 1 if ((yespct>.5 & issuescore3==1)|(yespct<.5 & issuescore3==-1)) & issuevalid3==1


* DISAGREE: Ideology and district view
gen DISAGREE1 = (ideotype~=districtview1) if issuevalid1==1 & ~missing(ideo) & rollvalid==1
gen DISAGREE2 = (ideotype~=districtview2) if issuevalid2==1 & ~missing(ideo) & rollvalid==1
gen DISAGREE3 = (ideotype~=districtview3) if issuevalid3==1 & ~missing(ideo) & rollvalid==1
gen DISAGREEp = (party~=districtview1)  if issuevalid1==1 & ~missing(party) & rollvalid==1
gen AGREE1 = (ideotype==districtview1) if issuevalid1==1 & ~missing(ideo)
gen AGREE2 = (ideotype==districtview2) if issuevalid2==1 & ~missing(ideo)
gen AGREE3 = (ideotype==districtview3) if issuevalid3==1 & ~missing(ideo)

* Term limits
gen termstate = (state=="CA" | state=="CO" | state=="ME" | state=="MI" | state=="OH" | state=="SD") 
gen termlim = (Term-yearroll)
gen lastterm = 0 if termstate==1
replace lastterm = 1 if (state=="CA" & termlim<2 & Chamber=="House")
replace lastterm = 1 if (state=="CA" & termlim<4 & Chamber=="Senate")
replace lastterm = 1 if (state=="CO" & termlim<2 & Chamber=="House")
replace lastterm = 1 if (state=="CI" & termlim<4 & Chamber=="Senate")
replace lastterm = 1 if (state=="ME" & termlim<2)
replace lastterm = 1 if (state=="MI" & termlim<2 & Chamber=="House")
replace lastterm = 1 if (state=="MI" & termlim<4 & Chamber=="Senate")
replace lastterm = 1 if (state=="OH" & Chamber=="Senate" & termlim<4 )
replace lastterm = 1 if (state=="OH" & Chamber=="House" & termlim<2)
replace lastterm = 1 if (state=="SD" & termlim<2)
gen lasttermfull = lastterm
replace lasttermfull = 0 if missing(lastterm)
gen DISAGREE1_lastterm = DISAGREE1*lastterm
gen AGREE1_lastterm = AGREE1*lastterm
gen DISAGREE1_lasttermfull = DISAGREE1*lasttermfull
gen AGREE1_lasttermfull = AGREE1*lasttermfull
gen DISAGREE1_termstate = DISAGREE1*termstate


* District agreement based on presidential vote
gen ideodistmissing = missing(DemPres) | missing(RepPres)
gen ideodist = 1 if DemPres<RepPres & ideodistmissing==0
replace ideodist = -1 if DemPres>RepPres & ideodistmissing==0
gen DISAGREEdist1 = (ideodist~=districtview1) if issuevalid1==1 & ideodistmissing==0
gen DISAGREEdist2 = (ideodist~=districtview2) if issuevalid2==1 & ideodistmissing==0
gen DISAGREEdist3 = (ideodist~=districtview3) if issuevalid3==1 & ideodistmissing==0
gen AGREEdist1 = (DISAGREEdist1==0) if issuevalid1==1 & ideodistmissing==0
gen AGREEdist2 = (DISAGREEdist2==0) if issuevalid2==1 & ideodistmissing==0
gen AGREEdist3 = (DISAGREEdist3==0) if issuevalid3==1 & ideodistmissing==0


* Legislator and district ideology agreement
gen AGREElegdist = (ideodist==ideotype) if ~missing(ideo) & ideodistmissing==0

gen iXd1 = ideoyes1*districtyes
gen iXd2 = ideoyes2*districtyes
gen iXd3 = ideoyes3*districtyes
gen iXyespct1 = ideoyes1*yespct
gen iXyespct2 = ideoyes2*yespct
gen iXyes1 = iyes1*yespct
gen iXyes2 = iyes2*yespct

save temp, replace
clear

* Create yes/no votes on each measure
use temp
collapse (sum) rollyesN=rollyes (sum) rollnoN=rollno ///
 (sum) rollyesRN=rollyesR (sum) rollyesDN=rollyesD ///
 (sum) rollnoRN=rollnoR (sum) rollnoDN=rollnoD (mean) majgop, by(propno Chamber)
gen rctot = rollyesN+rollnoN
gen rcmargin = rollyesN-rollnoN
gen rcmarginpct = rcmargin/rctot


merge 1:m propno Chamber using temp

erase temp.dta

gen medH = (sal==3)
gen medM = (sal==2)
gen medL = (sal==1)

*-------------------------------------------------------------------------------

********************************************************************************
* FIGURE 1. Congruence and vote margin
********************************************************************************
/*

#delimit ;
lpoly cong closeness if DISAGREE1==1, noscatter bwidth(.15) ci lineop(lpattern(dash)) 
 addplot(lpolyci cong closeness if DISAGREE1==0, bwidth(.15))
 title("") xtitle("Vote Margin") ytitle("Congruence")
 legend(order(4 2) label(4 "ALIGNED") label(2 "NOT ALIGNED") size(small))
 xlabel(, labsize(small)) ylabel(, labsize(small)) xscale(titlegap(2)) yscale(titlegap(1))
 graphregion(color(white))
note("{it:Note.} Kernel regressions. A legislator's roll-call vote was congruent if it matched the district's majority opinion."
"Vote margin is the percentage difference in votes received by the top two candidates in the previous election."
"Regressions differ according to whether a legislator's ideology was aligned with district opinion on an issue."
"95% confidence intervals are shaded.", span);
#delimit cr
exit
*/


********************************************************************************
* FIGURE 2. Congruence and roll-call margin
********************************************************************************
/*

#delimit ;
lpoly cong rcmarginpct if DISAGREE1==1, noscatter bwidth(.15) ci lineop(lpattern(dash)) 
 addplot(lpolyci cong rcmarginpct if DISAGREE1==0, bwidth(.15))
 title("") xtitle("Roll-Call Margin") ytitle("Congruence")
 legend(order(4 2) label(4 "ALIGNED") label(2 "NOT ALIGNED") size(small))
 xlabel(, labsize(small)) ylabel(, labsize(small)) xscale(titlegap(2)) yscale(titlegap(1))
 graphregion(color(white))
note("{it:Note.} Kernel regressions. A legislator's roll-call vote was congruent if it matched the district's majority opinion."
"Roll-call margin is the ratio of votes for and against the law as a fraction of total votes. Regressions differ"
"according to whether a legislator's ideology was aligned with district opinion on an issue. 95% confidence"
"intervals are shaded.", span);
#delimit cr
exit
*/


********************************************************************************
* FIGURE 3. Congruence, AGREE, and margin
********************************************************************************

drop if closeness==1

#delimit ;
lpoly cong closeness, noscatter bwidth(.15) lineop(lpattern(dash)) 
 addplot(lpoly AGREE1 closeness, bwidth(.15))
 title("") subtitle(" ") xtitle("Vote Margin") ytitle("") 
 legend(label(1 "Congruence") label(2 "ALIGNED") size(small))
 xlabel(, labsize(small)) ylabel(.5 .6 .7 .8 .9, labsize(small)) 
 xscale(titlegap(2)) yscale(range (.5 .75) titlegap(1))
 graphregion(color(white))
note("{it:Note.} Kernel regressions. A legislator's roll-call vote was congruent if it matched the district's majority opinion."
"ALIGNED means that a legislator's ideology agreed with district majority opinion. Vote margin is the difference"
"in votes received by the top two candidates in the previous election as a fraction to top-two votes. Legislators"
"with uncontested elections are omitted", span);
#delimit cr
exit
*/



